package com.block.sms.service.impl;

import cn.hutool.core.util.PhoneUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.block.common.constant.AppRspCodeConstant;
import com.block.common.service.IApplicationInfoService;
import com.block.common.service.IChannelCommonService;
import com.block.common.service.LogFactory;
import com.block.common.vo.ResponseVo;
import com.block.db.entity.ApplicationInfo;
import com.block.db.entity.ChannelBaseInfo;
import com.block.db.entity.MemberBaseInfo;
import com.block.db.entity.SmsReportInfo;
import com.block.db.mapper.ChannelBaseInfoMapper;
import com.block.db.mapper.MemberBaseInfoMapper;
import com.block.db.mapper.SmsReportInfoMapper;
import com.block.sms.dto.SmsParamDTO;
import com.block.sms.service.ISendSmsService;
import com.block.sms.service.ISmsRecordService;
import groovy.util.logging.Slf4j;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;

import java.time.LocalTime;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;


@Service
@Slf4j
public class SendSmsServiceImpl implements ISendSmsService {
    private static final Logger log = LogFactory.getCommLog();

    @Autowired
    MemberBaseInfoMapper memberBaseInfoMapper;
    @Autowired
    IChannelCommonService channelCommonService;
    @Autowired
    IApplicationInfoService applicationInfoService;
    @Autowired
    ISmsRecordService smsRecordService;
    @Autowired
    RedisTemplate redisTemplate;
    @Autowired
    ChannelBaseInfoMapper channelBaseInfoMapper;
    @Autowired
    SmsReportInfoMapper smsReportInfoMapper;

    private static final int SMS_SEND_INTERVAL_DAYS = 3;

    private static final String SMS_SENT_KEY_PREFIX = "sms:sent:";
    /**
     * 中国移动号码
     * 139、138、137、136、135、134、147、150、151、152、157、158、159、178、182、183、184、187、188、198、195
     * 虚拟运营商号段: 1703、1705、1706、165
     **/
    private static final String MOBILE_PATTERN = "139、138、137、136、135、134、147、150、151、152、157、158、159、178、182、183、184、187、188、198、195";

    /**
     * 中国电信号码
     * 133、149、153、173、177、180、181、189、199、191
     **/
    private static final String TELECOM_PATTERN = "133、149、153、173、177、180、181、189、199、191";

    /**
     * 中国联通号码
     * 130、131、132、155、156、185、186、145、175、176、166、140
     **/
    private static final String UNICOM_PATTERN = "130、131、132、155、156、185、186、145、175、176、166、140";

    @Override
    @Scheduled(fixedRate = 60000)
    public ResponseVo sendSmsMarketing() {

        LocalDateTime now = LocalDateTime.now();
        LocalTime currentTime = now.toLocalTime();

        // 晚上8点到早上8点不执行（20:00 - 08:00）
        if (currentTime.isAfter(LocalTime.of(20, 0)) || currentTime.isBefore(LocalTime.of(8, 0))) {
            log.info("当前时间{}不在执行时间段内（8:00-20:00），跳过短信发送", currentTime);
            return new ResponseVo(AppRspCodeConstant.SUCCESS, "不在执行时间段内");
        }

        LocalDateTime startTime;
        LocalDateTime endTime;

        if (currentTime.getHour() == 10 && currentTime.getMinute() >= 0 && currentTime.getMinute() <= 5) {
            startTime = now.minusDays(1).withHour(20).withMinute(0).withSecond(0).withNano(0);
            endTime = now.withHour(10).withMinute(0).withSecond(0).withNano(0);
        } else {
            startTime = now.minusMinutes(6);
            endTime = now.minusMinutes(5);
        }

        List<MemberBaseInfo> allUsers = memberBaseInfoMapper.getBaseUserInfoByCreateTime(startTime,endTime);
        List<String> codes = channelBaseInfoMapper.getCodeByStatus(1);

        Set<String> codeSet = new HashSet<>(codes);

        List<MemberBaseInfo> users = allUsers.stream()
                .filter(user -> codeSet.contains(user.getChannelCode()))
                .collect(Collectors.toList());

        if (users.isEmpty()) {
            return new ResponseVo(AppRspCodeConstant.SUCCESS, "没有需要处理的用户");
        }

        Map<String, List<MemberBaseInfo>> usersByCarrier = users.stream()
                .collect(Collectors.groupingBy(this::getCarrierByMobile));

        List<MemberBaseInfo> mobileUsers = usersByCarrier.getOrDefault("移动", new ArrayList<>());
        List<MemberBaseInfo> telecomUsers = usersByCarrier.getOrDefault("电信", new ArrayList<>());
        List<MemberBaseInfo> unicomUsers = usersByCarrier.getOrDefault("联通", new ArrayList<>());

        // 分别处理各运营商用户
        List<MemberBaseInfo> mobileUsersToProcess = filterUsersNeedSms(mobileUsers);
        List<MemberBaseInfo> telecomUsersToProcess = filterUsersNeedSms(telecomUsers);
        List<MemberBaseInfo> unicomUsersToProcess = filterUsersNeedSms(unicomUsers);

        processUsers(mobileUsersToProcess, "移动用户");
        processUsers(telecomUsersToProcess, "电信用户");
        processUsers(unicomUsersToProcess, "联通用户");

        updateSmsSentRecords(mobileUsersToProcess);
        updateSmsSentRecords(telecomUsersToProcess);
        updateSmsSentRecords(unicomUsersToProcess);

        int unicom = unicomUsersToProcess.size();
        int telecom = telecomUsersToProcess.size();
        int mobile = mobileUsersToProcess.size();
        return new ResponseVo(AppRspCodeConstant.SUCCESS,
                "短信提醒发送完成，共处理" + unicom + "条联通手机记录" + telecom + "条电信手机记录" + mobile + "条移动手机记录");

    }

    /**
     * 根据手机号判断运营商
     */
    private String getCarrierByMobile(MemberBaseInfo member) {
        String mobile = member.getMobile();
        if (mobile == null || mobile.length() < 3) {
            return "未知";
        }

        String prefix = mobile.substring(0, 3);
        if (MOBILE_PATTERN.contains(prefix)) {
            return "移动";
        } else if (TELECOM_PATTERN.contains(prefix)) {
            return "电信";
        } else if (UNICOM_PATTERN.contains(prefix)) {
            return "联通";
        }
        return "未知";
    }


    private List<MemberBaseInfo> filterUsersNeedSms(List<MemberBaseInfo> users) {
        return users.stream()
                .filter(user -> {
                    String redisKey = SMS_SENT_KEY_PREFIX + user.getMobile();
                    // 检查Redis中是否存在记录
                    return !redisTemplate.hasKey(redisKey);
                })
                .collect(Collectors.toList());
    }

    /**
     * 更新Redis发送记录（设置3天过期）
     */
    private void updateSmsSentRecords(List<MemberBaseInfo> users) {
        users.forEach(user -> {
            String redisKey = SMS_SENT_KEY_PREFIX + user.getMobile();
            redisTemplate.opsForValue().set(redisKey, "1", SMS_SEND_INTERVAL_DAYS, TimeUnit.DAYS);
        });
    }

    private void processUsers(List<MemberBaseInfo> users, String userType) {
        if (users == null || users.isEmpty()) {
            log.info("没有{}需要发送提醒", userType);
            return;
        }

        List<MemberBaseInfo> eligibleMembers = users.stream()
                .filter(member -> {
                    try {
                        if (!PhoneUtil.isMobile(member.getMobile())) {
                            log.warn("[{}]手机号格式不正确: {}", userType, member.getMobile());
                            return false;
                        }
                        ChannelBaseInfo channelInfo = channelCommonService.getBaseInfoByCode(member.getChannelCode());

                        return channelInfo != null && channelInfo.getSmsSendStatus() == 1;
                    } catch (Exception e) {
                        log.error("[{}]渠道状态检查异常 - 手机号: {}", userType, member.getMobile(), e);
                        return false;
                    }
                })
                .collect(Collectors.toList());

        eligibleMembers.forEach(member -> {
            try {
                SmsParamDTO smsParam = buildSmsParam(member);
                ChannelBaseInfo channelInfo = channelCommonService.getBaseInfoByCode(member.getChannelCode());
                ApplicationInfo appInfo = applicationInfoService.getAppInfoByAppCode(member.getRegAppCode());
                ResponseVo result = smsRecordService.sendSms(smsParam, appInfo, channelInfo);
                log.info("{}短信发送结果 - 手机号: {}, 结果: {}", userType, member.getMobile(), JSON.toJSONString(result));

            } catch (Exception e) {
                log.error("处理{}短信发送异常 - 手机号: {}", userType, member.getMobile(), e);
            }
        });
    }

    private SmsParamDTO buildSmsParam(MemberBaseInfo member) {
        SmsParamDTO smsParam = new SmsParamDTO();

        // 根据运营商设置不同的otype值
        String carrier = getCarrierByMobile(member);
        switch (carrier) {
            case "联通":
                smsParam.setOtype("3");
                break;
            case "移动":
                smsParam.setOtype("5");
                break;
            case "电信":
                smsParam.setOtype("6");
                break;
            default:
                smsParam.setOtype("");
                break;
        }

        smsParam.setMobie(member.getMobile());

        JSONArray params = new JSONArray();
        smsParam.setParamArray(params);

        return smsParam;
    }

    @Scheduled(cron = "0 0 8 * * ?")
    public void scheduledQuerySmsRecordResult() {
        log.info("开始执行定时短信状态查询任务");
        try {
            smsRecordService.querySmsRecordResult();
            log.info("定时短信状态查询任务执行完成");
        } catch (Exception e) {
            log.error("定时短信状态查询任务执行异常", e);
        }
    }


    @Scheduled(cron = "0 30 10 * * ?")
    public void scheduledSendSmsMarketing() {
        log.info("开始执行定时营销短信发送任务");
        try {
            // 计算72小时前的时间
            LocalDateTime threeDaysAgo = LocalDateTime.now().minusHours(72);

            // 查询lq_report_info表中状态为0且reportTime为72小时前的数据
            List<SmsReportInfo> reportInfos = smsReportInfoMapper.selectList(
                    new QueryWrapper<SmsReportInfo>()
                            .eq("status", 0)
                            .le("report_time", threeDaysAgo)
            );

            if (reportInfos.isEmpty()) {
                log.info("没有需要处理的报告数据");
                return;
            }

            // 提取手机号并去重
            Set<String> mobiles = reportInfos.stream()
                    .map(SmsReportInfo::getMobile)
                    .filter(Objects::nonNull)
                    .collect(Collectors.toSet());

            // 根据手机号查询对应的用户信息
            List<MemberBaseInfo> users = memberBaseInfoMapper.selectList(
                    new QueryWrapper<MemberBaseInfo>()
                            .in("mobile", mobiles)
            );

            if (users.isEmpty()) {
                log.info("未找到需要处理的用户信息");
                return;
            }

            // 按运营商分组处理用户
            Map<String, List<MemberBaseInfo>> usersByCarrier = users.stream()
                    .collect(Collectors.groupingBy(this::getCarrierByMobile));

            List<MemberBaseInfo> mobileUsers = usersByCarrier.getOrDefault("移动", new ArrayList<>());
            List<MemberBaseInfo> telecomUsers = usersByCarrier.getOrDefault("电信", new ArrayList<>());
            List<MemberBaseInfo> unicomUsers = usersByCarrier.getOrDefault("联通", new ArrayList<>());

            // 分别处理各运营商用户
            List<MemberBaseInfo> mobileUsersToProcess = filterUsersNeedSms(mobileUsers);
            List<MemberBaseInfo> telecomUsersToProcess = filterUsersNeedSms(telecomUsers);
            List<MemberBaseInfo> unicomUsersToProcess = filterUsersNeedSms(unicomUsers);

            processUsers(mobileUsersToProcess, "移动用户");
            processUsers(telecomUsersToProcess, "电信用户");
            processUsers(unicomUsersToProcess, "联通用户");

            updateSmsSentRecords(mobileUsersToProcess);
            updateSmsSentRecords(telecomUsersToProcess);
            updateSmsSentRecords(unicomUsersToProcess);


            updateReportInfoStatus(reportInfos);

            int unicom = unicomUsersToProcess.size();
            int telecom = telecomUsersToProcess.size();
            int mobile = mobileUsersToProcess.size();
            log.info("定时营销短信发送任务执行完成 - " + "移动: {} 条, 电信: {} 条, 联通: {} 条", mobile, telecom, unicom);
        } catch (Exception e) {
            log.error("定时营销短信发送任务执行异常", e);
        }
    }

    private void updateReportInfoStatus(List<SmsReportInfo> reportInfos) {
        try {
            if (reportInfos == null || reportInfos.isEmpty()) {
                return;
            }

            // 提取手机号列表用于批量更新
            Set<String> mobiles = reportInfos.stream()
                    .map(SmsReportInfo::getMobile)
                    .filter(Objects::nonNull)
                    .collect(Collectors.toSet());

            if (!mobiles.isEmpty()) {
                // 批量更新状态为1
                SmsReportInfo updateEntity = new SmsReportInfo();
                updateEntity.setStatus(1);

                QueryWrapper<SmsReportInfo> updateWrapper = new QueryWrapper<>();
                updateWrapper.in("mobile", mobiles);

                smsReportInfoMapper.update(updateEntity, updateWrapper);
                log.info("成功更新 {} 条reportInfo记录状态为1", mobiles.size());
            }
        } catch (Exception e) {
            log.error("更新reportInfo状态时发生异常", e);
        }
    }

}